"""
用户购买接口测试
测试用户购买记录的添加和查询功能
"""

import requests
import json
import time

base_url = "http://localhost:8080/api"
purchases_url = f"{base_url}/purchases"
users_url = f"{base_url}/users"
books_url = f"{base_url}/books"


def login_user(username, password):
    """用户登录并返回token"""
    login_data = {"username": username, "password": password}
    response = requests.post(
        f"{users_url}/login",
        json=login_data,
        headers={"Content-Type": "application/json"},
    )
    if response.status_code == 200:
        return response.json().get("token")
    else:
        print(f"登录失败: {response.json()}")
        return None


def register_user(username, password):
    """用户注册"""
    register_data = {"username": username, "password": password}
    response = requests.post(
        f"{users_url}/register",
        json=register_data,
        headers={"Content-Type": "application/json"},
    )
    return response.status_code == 200


def get_book_info(book_id):
    """获取图书信息"""
    try:
        response = requests.get(f"{books_url}/get?book_id={book_id}")
        if response.status_code == 200:
            book_data = response.json()
            # 从响应中提取book_data字段
            if "book_data" in book_data:
                return book_data["book_data"]
            return book_data
        else:
            print(f"获取图书信息失败，状态码: {response.status_code}")
            print(f"响应内容: {response.json()}")
            return None
    except Exception as e:
        print(f"获取图书信息失败: {e}")
        return None


def test_purchases_info():
    """测试获取购买管理接口信息"""
    print("=== 测试获取购买管理接口信息 ===")

    try:
        response = requests.get(f"{purchases_url}/")

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {json.dumps(response.json(), ensure_ascii=False, indent=2)}")

        if response.status_code == 200:
            print("✅ 获取购买接口信息成功")
            return True
        else:
            print("❌ 获取购买接口信息失败")
            return False

    except Exception as e:
        print(f"❌ 获取购买接口信息请求异常: {e}")
        return False


def test_purchase_book(token, book_id=1, price=29.8):
    """测试购买图书"""
    print(f"\n=== 测试购买图书 (book_id: {book_id}, price: {price}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    data = {"book_id": book_id, "price": price}

    try:
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {json.dumps(response.json(), ensure_ascii=False, indent=2)}")

        if response.status_code == 200:
            print("✅ 购买图书成功")
            return True
        else:
            print("❌ 购买图书失败")
            return False

    except Exception as e:
        print(f"❌ 购买图书请求异常: {e}")
        return False


def test_purchase_with_wrong_price(token, book_id=1, wrong_price=99.9):
    """测试使用错误价格购买图书"""
    print(
        f"\n=== 测试错误价格购买 (book_id: {book_id}, wrong_price: {wrong_price}) ==="
    )

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    data = {"book_id": book_id, "price": wrong_price}

    try:
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {response.json()}")

        if response.status_code == 400 and "价格不正确" in response.json().get(
            "message", ""
        ):
            print("✅ 错误价格验证成功")
            return True
        else:
            print("❌ 错误价格验证失败")
            return False

    except Exception as e:
        print(f"❌ 错误价格测试请求异常: {e}")
        return False


def test_duplicate_purchase(token, book_id=1, price=29.8):
    """测试重复购买同一本书"""
    print(f"\n=== 测试重复购买 (book_id: {book_id}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    data = {"book_id": book_id, "price": price}

    try:
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {response.json()}")

        if response.status_code == 400 and "已经购买过" in response.json().get(
            "message", ""
        ):
            print("✅ 重复购买验证成功")
            return True
        else:
            print("❌ 重复购买验证失败")
            return False

    except Exception as e:
        print(f"❌ 重复购买测试请求异常: {e}")
        return False


def test_purchase_nonexistent_book(token, book_id=999999, price=29.8):
    """测试购买不存在的图书"""
    print(f"\n=== 测试购买不存在的图书 (book_id: {book_id}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    data = {"book_id": book_id, "price": price}

    try:
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {response.json()}")

        if response.status_code == 400 and "图书不存在" in response.json().get(
            "message", ""
        ):
            print("✅ 不存在图书验证成功")
            return True
        else:
            print("❌ 不存在图书验证失败")
            return False

    except Exception as e:
        print(f"❌ 不存在图书测试请求异常: {e}")
        return False


def test_get_purchase_record(token, book_id=1):
    """测试查询购买记录"""
    print(f"\n=== 测试查询购买记录 (book_id: {book_id}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    try:
        response = requests.get(
            f"{purchases_url}/get?book_id={book_id}", headers=headers
        )

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {json.dumps(response.json(), ensure_ascii=False, indent=2)}")

        if response.status_code == 200:
            print("✅ 查询购买记录成功")
            return response.json()
        elif response.status_code == 400 and "未找到购买记录" in response.json().get(
            "message", ""
        ):
            print("✅ 未找到购买记录（预期行为）")
            return None
        else:
            print("❌ 查询购买记录失败")
            return False

    except Exception as e:
        print(f"❌ 查询购买记录请求异常: {e}")
        return False


def test_get_nonexistent_purchase_record(token, book_id=999):
    """测试查询不存在的购买记录"""
    print(f"\n=== 测试查询不存在的购买记录 (book_id: {book_id}) ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    try:
        response = requests.get(
            f"{purchases_url}/get?book_id={book_id}", headers=headers
        )

        print(f"状态码: {response.status_code}")
        print(f"响应内容: {response.json()}")

        if response.status_code == 400 and "未找到购买记录" in response.json().get(
            "message", ""
        ):
            print("✅ 查询不存在购买记录验证成功")
            return True
        else:
            print("❌ 查询不存在购买记录验证失败")
            return False

    except Exception as e:
        print(f"❌ 查询不存在购买记录请求异常: {e}")
        return False


def test_unauthorized_access():
    """测试未授权访问"""
    print("\n=== 测试未授权访问 ===")

    try:
        # 测试没有token的购买
        data = {"book_id": 1, "price": 29.8}
        headers = {"Content-Type": "application/json"}
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)
        print(f"无token购买 - 状态码: {response.status_code}")

        # 测试没有token的查询
        response = requests.get(f"{purchases_url}/get?book_id=1", headers=headers)
        print(f"无token查询 - 状态码: {response.status_code}")

        # 测试无效token
        headers = {
            "Authorization": "Bearer invalid_token",
            "Content-Type": "application/json",
        }
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)
        print(f"无效token购买 - 状态码: {response.status_code}")

        if response.status_code == 401:
            print("✅ 未授权访问验证成功")
            return True
        else:
            print("❌ 未授权访问验证失败")
            return False

    except Exception as e:
        print(f"❌ 未授权访问测试异常: {e}")
        return False


def test_invalid_parameters(token):
    """测试无效参数"""
    print("\n=== 测试无效参数 ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    try:
        # 测试缺少book_id
        data = {"price": 29.8}
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)
        print(f"缺少book_id - 状态码: {response.status_code}")

        # 测试缺少price
        data = {"book_id": 1}
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)
        print(f"缺少price - 状态码: {response.status_code}")

        # 测试负数价格
        data = {"book_id": 1, "price": -10.0}
        response = requests.post(f"{purchases_url}/buy", json=data, headers=headers)
        print(f"负数价格 - 状态码: {response.status_code}")

        # 测试查询时缺少book_id参数
        response = requests.get(f"{purchases_url}/get", headers=headers)
        print(f"查询时缺少book_id - 状态码: {response.status_code}")

        if response.status_code == 422:  # FastAPI参数验证错误
            print("✅ 无效参数验证成功")
            return True
        else:
            print("❌ 无效参数验证失败")
            return False

    except Exception as e:
        print(f"❌ 无效参数测试异常: {e}")
        return False


def test_complete_purchase_flow(token):
    """测试完整的购买流程"""
    print("\n=== 测试完整购买流程 ===")

    if not token:
        print("❌ 没有有效的token，跳过测试")
        return False

    book_id = 2

    # 1. 首先查询是否已购买
    print(f"1. 查询图书 {book_id} 的购买状态")
    initial_status = test_get_purchase_record(
        token, book_id
    )  # 2. 获取图书信息和正确价格
    print(f"2. 获取图书 {book_id} 的信息")
    book_info = get_book_info(book_id)
    if not book_info:
        print("❌ 无法获取图书信息，跳过完整流程测试")
        return False

    book_price = book_info.get("price")
    if book_price is None:
        print("❌ 图书信息中缺少价格，跳过完整流程测试")
        return False

    print(f"图书价格: {book_price}")

    # 3. 如果未购买，则进行购买
    if initial_status is None:
        print(f"3. 购买图书 {book_id}")
        purchase_success = test_purchase_book(token, book_id, book_price)

        if purchase_success:
            # 4. 验证购买成功
            print(f"4. 验证购买结果")
            final_status = test_get_purchase_record(token, book_id)

            if final_status:
                print("✅ 完整购买流程测试成功")
                return True
            else:
                print("❌ 购买后查询失败")
                return False
        else:
            print("❌ 购买失败")
            return False
    else:
        print("图书已购买，测试重复购买")
        # 如果已购买，测试重复购买
        duplicate_result = test_duplicate_purchase(token, book_id, book_price)
        if duplicate_result:
            print("✅ 重复购买验证成功")
            return True
        else:
            print("❌ 重复购买验证失败")
            return False


def test_books_api_connection():
    """测试图书接口连接"""
    print("\n=== 测试图书接口连接 ===")

    try:
        # 测试图书接口信息
        response = requests.get(f"{books_url}/")
        print(f"图书接口信息 - 状态码: {response.status_code}")

        if response.status_code == 200:
            print("✅ 图书接口连接成功")

            # 测试获取图书详情
            test_book_id = 1
            book_info = get_book_info(test_book_id)
            if book_info:
                price = book_info.get("price")
                print(f"✅ 成功获取图书ID {test_book_id} 的信息，价格: {price}")
                return True, price
            else:
                print(f"❌ 无法获取图书ID {test_book_id} 的详细信息")
                return False, None
        else:
            print("❌ 图书接口连接失败")
            return False, None

    except Exception as e:
        print(f"❌ 图书接口连接异常: {e}")
        return False, None


def run_all_purchases_tests():
    """运行所有购买功能测试"""
    print("开始用户购买功能测试...")
    print("=" * 80)

    # 测试用户名（使用时间戳确保唯一性）
    username = f"purchase_test_user_{int(time.time())}"
    password = "123456"

    # 1. 注册测试用户
    print(f"注册测试用户: {username}")
    if not register_user(username, password):
        print("❌ 用户注册失败，测试终止")
        return

    # 2. 登录获取token
    print(f"登录测试用户: {username}")
    token = login_user(username, password)
    if not token:
        print("❌ 用户登录失败，测试终止")
        return print(f"✅ 获得token: {token[:20]}...")

    # 3. 测试图书接口连接
    books_available, default_price = test_books_api_connection()
    if not books_available:
        print("❌ 图书接口不可用，测试终止")
        return

    # 4. 测试获取购买接口信息
    test_purchases_info()

    # 5. 测试未授权访问
    test_unauthorized_access()

    # 6. 测试无效参数
    test_invalid_parameters(token)  # 7. 测试查询未购买的图书
    test_get_nonexistent_purchase_record(token, book_id=1)

    # 8. 测试购买不存在的图书
    test_purchase_nonexistent_book(token)

    # 9. 获取图书信息用于测试（确保能获取到）
    book_info = get_book_info(1)
    if book_info and "price" in book_info:
        book_price = book_info["price"]
        print(f"\n✅ 使用图书ID: 1, 价格: {book_price}")

        # 10. 测试错误价格购买
        test_purchase_with_wrong_price(token, book_id=1, wrong_price=99.9)

        # 11. 测试正常购买
        test_purchase_book(token, book_id=1, price=book_price)

        # 12. 测试查询购买记录
        test_get_purchase_record(token, book_id=1)

        # 13. 测试重复购买
        test_duplicate_purchase(token, book_id=1, price=book_price)
    else:
        # 使用默认价格作为备选方案
        print(f"\n⚠️ 图书详情中无价格信息，使用默认价格: {default_price}")
        if default_price:
            test_purchase_book(token, book_id=1, price=default_price)
            test_get_purchase_record(token, book_id=1)
        else:
            print("❌ 无法获取有效价格信息，跳过购买测试")

    # 14. 测试完整购买流程
    test_complete_purchase_flow(token)  # 15. 最终状态验证
    print(f"\n=== 验证最终购买状态 ===")
    test_get_purchase_record(token, book_id=1)
    test_get_purchase_record(token, book_id=2)

    print("\n" + "=" * 80)
    print("用户购买功能测试完成")


if __name__ == "__main__":
    run_all_purchases_tests()
